package com.longtop.framework.sys.file.supports;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpUtils;

import com.longtop.framework.security.BaseUncheckedException;
import com.longtop.framework.util.StringUtil;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.FileRenamePolicy;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.ParamPart;
import com.oreilly.servlet.multipart.Part;

public class BaseMultipartRequest {

	@SuppressWarnings("unchecked")
	protected Hashtable parameters = new Hashtable();
	@SuppressWarnings("unchecked")
	protected Hashtable files = new Hashtable();

	protected FileRenamePolicy policy = new DefaultFileRenamePolicy();

	protected String allowFile;

	public void setAllowFile(String allowFile) {
		this.allowFile = allowFile;
	}

	protected String notAllowFile;

	public void setNotAllowFile(String notAllowFile) {
		this.notAllowFile = notAllowFile;
	}

	protected boolean validatorTrue(String file) {
		String files = StringUtil.getString(allowFile);
		if (files.length() > 0) {
			if (files.indexOf(",") != -1) {
				String filesT[] = StringUtil.split(files, ",");
				return !StringUtil.noInString(file, filesT);
			} else {
				return file.equalsIgnoreCase(files);
			}
		}
		return true;

	}

	protected boolean validatorFalse(String file) {
		String files = StringUtil.getString(notAllowFile);
		if (files.length() > 0) {
			if (files.indexOf(",") != -1) {
				String filesT[] = StringUtil.split(files, ",");
				return StringUtil.noInString(file, filesT);
			} else {
				return !file.equalsIgnoreCase(files);
			}
		}
		return true;

	}

	@SuppressWarnings("unchecked")
	public List MultipartUpLoad(HttpServletRequest request, String saveDirectory, long maxPostSize, String encoding) throws Exception {
		if (request == null)
			throw new IllegalArgumentException("request cannot be null");
		if (saveDirectory == null)
			throw new IllegalArgumentException("saveDirectory cannot be null");
		// if (maxPostSize <= 0) {
		// throw new IllegalArgumentException("maxPostSize must be positive");
		// }

		// FileControl dir = new FileControl();
		// dir.setMyFile(new File(saveDirectory));
		// dir.createDirectory();

		File upFiles = new File(saveDirectory);
		MultipartParser parser = null;
		parser = new MultipartParser(request, maxPostSize, true, true, encoding);

		if (request.getQueryString() != null) {

			Hashtable queryParameters = HttpUtils.parseQueryString(request.getQueryString());

			Enumeration queryParameterNames = queryParameters.keys();
			while (queryParameterNames.hasMoreElements()) {
				Object paramName = queryParameterNames.nextElement();
				String[] values = (String[]) queryParameters.get(paramName);
				Vector newValues = new Vector();
				for (int i = 0; i < values.length; i++) {
					newValues.add(values[i]);
				}
				parameters.put(paramName, newValues);
			}
		}

		Part part;
		try {
			while ((part = parser.readNextPart()) != null) {
				String name = part.getName();
				if (part.isParam()) {

					ParamPart paramPart = (ParamPart) part;
					String value = paramPart.getStringValue();
					Vector existingValues = (Vector) parameters.get(name);
					if (existingValues == null) {
						existingValues = new Vector();
						parameters.put(name, existingValues);
					}
					existingValues.addElement(value);
				} else if (part.isFile()) {

					FilePart filePart = (FilePart) part;
					String fileName = filePart.getFileName();
					String fileEXT = StringUtil.getFileEXT(fileName);

					if (fileName != null) {
						if (!validatorTrue(fileEXT) || !validatorFalse(fileEXT)) {

							throw new BaseUncheckedException("传入的文件格式不正确");

						}
						filePart.setRenamePolicy(policy);
						long size = filePart.writeTo(upFiles);
						if (files.size() > 0) {
							if (files.containsKey(name)) {
								Object objFiles = files.get(name);
								if (objFiles.getClass().isArray()) {
									UploadedFile[] objArray = (UploadedFile[]) objFiles;
									UploadedFile[] upArray = new UploadedFile[objArray.length + 1];
									for (int i = 0; i < upArray.length - 1; i++) {
										upArray[i] = objArray[i];
									}
									UploadedFile upeds = new UploadedFile(upFiles.getPath(), filePart.getFileName(), fileName, filePart.getContentType(), size);
									upArray[objArray.length] = upeds;
									files.put(name, upArray);

								} else {
									UploadedFile[] uped = new UploadedFile[2];
									uped[0] = (UploadedFile) objFiles;
									UploadedFile upeds = new UploadedFile(upFiles.getPath(), filePart.getFileName(), fileName, filePart.getContentType(), size);
									uped[1] = upeds;
									files.put(name, uped);
								}
							} else {
								files.put(name, new UploadedFile(upFiles.getPath(), filePart.getFileName(), fileName, filePart.getContentType(), size));
							}
						} else {
							files.put(name, new UploadedFile(upFiles.getPath(), filePart.getFileName(), fileName, filePart.getContentType(), size));
						}

					}
				}
			}
		} catch (IOException e) {
			throw new BaseUncheckedException(e.getMessage());
		}
		return null;
	}

	public BaseMultipartRequest() {

	}

	@SuppressWarnings("unchecked")
	public Enumeration getParameterNames() {
		return parameters.keys();
	}

	@SuppressWarnings("unchecked")
	public Map getParameterMap() {
		Map pMap = new HashMap();
		Enumeration paramsMap = getParameterNames();
		if (paramsMap != null) {
			while (paramsMap.hasMoreElements()) {
				String pa = paramsMap.nextElement().toString();
				pMap.put(pa, getParameter(pa));
			}
		}
		return pMap;
	}

	@SuppressWarnings("unchecked")
	public Enumeration getFileNames() {
		return files.keys();
	}

	@SuppressWarnings("unchecked")
	public String getParameter(String name) {
		try {
			Vector values = (Vector) parameters.get(name);
			if (values == null || values.size() == 0) {
				return null;
			}
			String value = (String) values.elementAt(values.size() - 1);
			return value;
		} catch (Exception e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public String[] getParameterValues(String name) {
		try {
			Vector values = (Vector) parameters.get(name);
			if (values == null || values.size() == 0) {
				return null;
			}
			String[] valuesArray = new String[values.size()];
			values.copyInto(valuesArray);
			return valuesArray;
		} catch (Exception e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public String[] getFilesystemNames() {
		if (files != null && files.size() > 0) {
			String[] strFileSystemNames = new String[files.size()];
			int i = 0;
			for (Iterator iter = files.entrySet().iterator(); iter.hasNext();) {

				Map.Entry entry = (Map.Entry) iter.next();
				strFileSystemNames[i] = entry.getValue() == null ? null : entry.getValue().toString();
				i++;
			}
			return strFileSystemNames;
		}
		return null;
	}

	public String getFilesystemName(String name) {
		try {
			UploadedFile file = (UploadedFile) files.get(name);
			return file.getFilesystemName(); // may be null
		} catch (Exception e) {
			return null;
		}
	}

	public long getFileSize(String name) {
		try {
			UploadedFile file = (UploadedFile) files.get(name);
			return file.getSize(); // may be null
		} catch (Exception e) {
			return 0;
		}
	}

	public String getOriginalFileName(String name) {
		try {
			UploadedFile file = (UploadedFile) files.get(name);
			return file.getOriginalFileName(); // may be null
		} catch (Exception e) {
			return null;
		}
	}

	public String getContentType(String name) {
		try {
			UploadedFile file = (UploadedFile) files.get(name);
			return file.getContentType(); // may be null
		} catch (Exception e) {
			return null;
		}
	}

	public File getFile(String name) {
		try {
			UploadedFile file = (UploadedFile) files.get(name);
			return file.getFile(); // may be null
		} catch (Exception e) {
			return null;
		}
	}

	public UploadedFile[] getUploadedFile(String name) {
		try {
			UploadedFile[] file = (UploadedFile[]) files.get(name);
			return file; // may be null
		} catch (Exception e) {
			return null;
		}
	}

	public boolean isArray(String name) {
		try {
			Object obj = files.get(name);
			return obj.getClass().isArray(); // may be null
		} catch (Exception e) {
			return false;
		}
	}

	@SuppressWarnings("unchecked")
	public Hashtable getParameters() {
		return parameters;
	}

	@SuppressWarnings("unchecked")
	public void setParameters(Hashtable parameters) {
		this.parameters = parameters;
	}

	public FileRenamePolicy getPolicy() {
		return policy;
	}

	public void setPolicy(FileRenamePolicy policy) {
		this.policy = policy;
	}
}

class UploadedFile {

	private String dir;
	private String filename;
	private String original;
	private String type;
	private long size;

	UploadedFile() {

	}

	UploadedFile(String dir, String filename, String original, String type, long size) {
		this.dir = dir;
		this.filename = filename;
		this.original = original;
		this.type = type;
		this.size = size;
	}

	public String getContentType() {
		return type;
	}

	public String getFilesystemName() {
		return filename;
	}

	public String getOriginalFileName() {
		return original;
	}

	public File getFile() {
		if (dir == null || filename == null) {
			return null;
		} else {
			return new File(dir + File.separator + filename);
		}
	}

	public long getSize() {
		return size;
	}

	public void setSize(long size) {
		this.size = size;
	}
}
